package name.fraser.neil.plaintext;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

//TIP 要<b>运行</b>代码，请按 <shortcut actionId="Run"/> 或
// 点击装订区域中的 <icon src="AllIcons.Actions.Execute"/> 图标。
public class DiffUtils {
    public static void main(String[] args) {
        DiffResult diffResult=diff("D:\\workspace\\diff\\diff\\master\\HelloWorld.java","D:\\workspace\\diff\\diff\\test\\HelloWorld.java");
        for(int i=0;i<diffResult.getRightList().size();i++){
            Line left=diffResult.getLeftList().get(i);
            Line right=diffResult.getRightList().get(i);
            System.out.printf("%1d %-80s",left.getLine(),left.getText());
            System.out.printf("%1d %-80s",right.getLine(),right.getText());
            System.out.print("\n");
        }
    }

    public static DiffResult diff(String leftFile,String rightFile){
        diff_match_patch diffMatchPatch=new diff_match_patch();
        String origin=readLines(leftFile);
        String current=readLines(rightFile);
        diff_match_patch.LinesToCharsResult lines=diffMatchPatch.diff_linesToChars(origin,current);
        String linePrev = lines.chars1;
        String lineCurrent = lines.chars2;
        List<String> lineArray = lines.lineArray;
        LinkedList<diff_match_patch.Diff> rows=diffMatchPatch.diff_main(linePrev,lineCurrent,false);
        diffMatchPatch.diff_charsToLines(rows,lineArray);
        List<Line> lefts=new ArrayList<>();
        List<Line> rights=new ArrayList<>();
        DiffResult diffResult=new DiffResult();
        diffResult.setLeftList(lefts);
        diffResult.setRightList(rights);
        int leftLine=1;
        int rightLine=1;
        Line lastLine=null;
        boolean isSkip=false;
        for(int next=0;next<rows.size();next++){
            diff_match_patch.Diff diff = rows.get(next);
            if(isSkip){
                isSkip=false;
                continue;
            }
            if((next+1)<rows.size()) {
                diff_match_patch.Diff nexeDiff = rows.get(next + 1);
                if (diff.operation == diff_match_patch.Operation.DELETE) {
                    if(nexeDiff.operation == diff_match_patch.Operation.EQUAL) {
                        List<String> leftLines = splitLeftLines(diff.text, "-");
                        for (String left : leftLines) {
                            Line line = new Line();
                            line.setText(left);
                            line.setLine(leftLine);
                            line.setType(1);
                            Line line2 = new Line();
                            line2.setText("");
                            line2.setLine(-1);
                            line2.setType(-1);
                            leftLine++;
                            lefts.add(line);
                            rights.add(line2);
                        }
                    }
                    if (nexeDiff.operation == diff_match_patch.Operation.INSERT) {
                        isSkip=true;
                        List<String> leftLines = splitLeftLines(diff.text, "-");
                        List<String> rightLines = splitRightLines(nexeDiff.text, "+");
                        int size=Math.max(leftLines.size(),rightLines.size());
                        for(int j=0;j<size;j++){
                            Line line = new Line();
                            Line line2 = new Line();
                            line.setLine(-1);
                            line.setType(-1);
                            line2.setLine(-1);
                            line2.setType(-1);
                            String left="";
                            String right="";
                            if(j<leftLines.size()){
                                left=leftLines.get(j);
                                line.setLine(leftLine);
                                line.setType(1);
                                leftLine++;
                            }
                            if(j<rightLines.size()){
                                right=rightLines.get(j);
                                line2.setLine(rightLine);
                                line2.setType(2);
                                rightLine++;
                            }
                            line.setText(left);
                            line2.setText(right);
                            lefts.add(line);
                            rights.add(line2);
                        }
                    }
                }
            }
            if(diff.operation== diff_match_patch.Operation.EQUAL) {
                List<String> equalsLines=splitEqualsLines(diff.text," ");
                for(String equals:equalsLines){
                    Line line=new Line();
                    line.setText(equals);
                    line.setLine(leftLine);
                    line.setType(0);
                    Line line2=new Line();
                    line2.setText(equals);
                    line2.setLine(rightLine);
                    line2.setType(0);
                    leftLine++;
                    rightLine++;
                    lefts.add(line);
                    rights.add(line2);
                }
            }
            if(diff.operation== diff_match_patch.Operation.INSERT) {
                List<String> rightLines=splitRightLines(diff.text,"+");
                for(String right:rightLines){
                    Line line=new Line();
                    line.setText("");
                    line.setLine(-1);
                    Line line2=new Line();
                    line2.setText(right);
                    line2.setLine(rightLine);
                    line2.setType(2);
                    rightLine++;
                    lefts.add(line);
                    rights.add(line2);
                }
            }

        }
        return diffResult;
    }
    private static List<String> splitLeftLines(String lines,String prefix){
        List<String> temp=lines.lines().toList();
        List<String> result=new ArrayList<>();
        for(int i=0;i<temp.size();i++){
            String line=temp.get(i);
            if(prefix.equals("-")){
                result.add(prefix+line);
            }
        }
        return result;
    }
    private static List<String> splitRightLines(String lines,String prefix){
        List<String> temp=lines.lines().toList();
        List<String> result=new ArrayList<>();
        for(int i=0;i<temp.size();i++){
            String line=temp.get(i);
            if(prefix.equals("+")){
                result.add(prefix+line);
            }
        }
        return result;
    }
    private static List<String> splitEqualsLines(String lines,String prefix){
        List<String> temp=lines.lines().toList();
        List<String> result=new ArrayList<>();
        for(int i=0;i<temp.size();i++){
            String line=temp.get(i);
            result.add(prefix+line);
        }
        return result;
    }

    private static String readLines(String fileName){
        StringBuffer sb=new StringBuffer();
        List<String> lines = null;
        try {
            lines = Files.readAllLines(Paths.get(fileName));
            for(String line:lines){
                sb.append(line).append("\n");
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return sb.toString();
    }
}